import { log } from "cc";
import { GlobalEventMgr } from "../platform/event/GlobalEventMgr";
import { IScript } from "./IScript";
import { MoveData } from "./MoveData";
import { MsgTypes } from "./MsgTypes";
import { SyncDemoEvent } from "./SyncDemoEvent";

export function script(){
    return function <T extends new (...args: any[]) => IScript<any>>(constructor: T) {
        // 将装饰的类注册到 NetworkManager
        // if(!IScript.prototype.isPrototypeOf(constructor.prototype)){
        //     console.error(`${constructor.name} 必须实现 IScript 接口`);
        //     return
        // }
        let types = NetworkManager.prototype["__script_types"]
        if(!types){
            types = new Set()
            NetworkManager.prototype["__script_types"] = types
        }
        types.add(constructor);
        return constructor;
    };
}

export class NetworkManager {
    private static instance: NetworkManager;
    private ws: WebSocket | null = null;
    private serverTimeOffset: number = 0;
    private moveSequence: number = 0;
    private pendingMoves: Map<number, MoveData> = new Map();
    private scripts: Map<string, IScript<any>> = new Map();

    constructor(){
        let types:Set<any> = NetworkManager.prototype["__script_types"]
        if(!types){
            return
        }
        types.forEach((type)=>{
            let scriptInstance = new type();
            this.scripts.set(scriptInstance.getType(), scriptInstance);
        })
    }

    
    public static getInstance(): NetworkManager {
        if (!NetworkManager.instance) {
            NetworkManager.instance = new NetworkManager();
        }
        return NetworkManager.instance;
    }

    connect(connectedCb?: () => void,closeCb?: () => void){
        this.ws = new WebSocket('ws://127.0.0.1:8081/ws'); 
        this.ws.onopen = () => {
            console.log("WebSocket connected");
            // 在这里可以发送登录信息等初始化操作
            connectedCb?.()
        };
        this.ws.onmessage = (event) => {
            const message = JSON.parse(event.data);
            this.onMessage(message);
        };
        this.ws.onerror = (event) => {
            console.error("WebSocket error:", event);
        };
        this.ws.onclose = () => {
            console.log("WebSocket closed");
            closeCb?.()
        };
    }
    
    // 服务器时间同步
    public async syncServerTime(): Promise<void> {
        // return new Promise((resolve) => {
        //     // 发送时间同步请求
        //     this.sendMessage({ type: 'TIME_SYNC', data: Date.now() });
            
        //     // 服务器会返回时间响应，在onMessage中处理
        //     setTimeout(resolve, 1000);
        // });
    }
    
    public  getServerTime(): number {
        return Date.now() + this.serverTimeOffset;
    }
    
    // 发送移动消息
    public sendMove(moveData: MoveData): void {
        this.moveSequence++;
        moveData.sequence = this.moveSequence;
        moveData.clientTime = this.getServerTime();
        
        this.pendingMoves.set(this.moveSequence, moveData);
        this.sendMessage(MsgTypes.Move, moveData);
    }
    private onMessage(message: {type:string,code:number,data:any}): void {
        console.log("Received message:", message);
        const script = this.scripts.get(message.type);
        if (script) {
            script.handle(message);
        }else{
            console.error("No script found for message type:", message.type);   
        }
    }
    // 处理服务器消息
    // private onMessage(message: any): void {
    //     switch (message.type) {
    //         case 'TIME_SYNC_RESPONSE':
    //             this.handleTimeSync(message);
    //             break;
    //         case 'GAME_STATE':
    //             // this.handleGameState(message.states);
    //             break;
    //         case MsgTypes.Login:
    //             // this.handleGameState(message.states);
    //             GlobalEventMgr.ins.emit(SyncDemoEvent.LoginSuccess,message.data)
    //             break;
    //         case MsgTypes.Move:
    //         // this.handleGameState(message.states);
    //         GlobalEventMgr.ins.emit(SyncDemoEvent.LoginSuccess,message.data)
    //         break;
    //     }
    // }
    
    private handleTimeSync(message: any): void {
        const now = Date.now();
        const rtt = now - message.clientTime;
        this.serverTimeOffset = message.serverTime - now + (rtt / 2);
    }


    public sendMessage(type:string,data:object = {}):void{
        const msg = {type,data}
        this.ws.send(JSON.stringify(msg));
    }
}